package com.vecspace.dicttable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import org.apache.commons.lang3.StringUtils;

/**
 * @author: wanghua
 */

public class CodeDict {
	public static ICodeDataSource s_dmDataSource;

	public ICodeDataSource getDmDataSource() {
		return s_dmDataSource;
	}

	public void setDmDataSource(ICodeDataSource dmDataSource) {
		s_dmDataSource = dmDataSource;
	}
	
	private static CodeDict dmdict;
	//需要定期检查代码表的更新状态。在系统配置表里添加一个配置项（long类型），用来记录字典表的更新，如果获取的值比当前加载时的值大，则清空缓存池，所有代码表从新加载
	public void clear(){
		tables.clear();
	}
	
	public synchronized static CodeDict getInstance(){
		if(dmdict == null){
			dmdict = new CodeDict();
		}
		return dmdict;
	}
	
	protected CodeDict(){
		tables = new HashMap<String,CodeTable>();
	}
	
	private Map<String,CodeTable> tables;//tableName,DMTable
	
	/**
	 * 根据类名获取字典代码值对应的名称值
	 * dmClazz必须包含CodeTableInfoAnnotation注解
	 * 功能描述：
	 * @param dmClazz dmClazz必须包含CodeTableInfoAnnotation注解
	 * @param code
	 * @return 
	 * @author: wanghua
	 */
	public String getItemName(Class<?> dmClazz, Object code){
		CodeTableInfoAnnotation anno = dmClazz.getAnnotation(CodeTableInfoAnnotation.class);
		if(anno != null){
			String codeName = getItemName(anno.TableName(), anno.CodeField(),
					anno.NameField(),anno.OrderField(),code, true);
			return codeName;
		}else {
			return code.toString();
		}
	}
	
	/**
	 * 
	 * 功能描述：
	 * @param tableName     字典表名
	 * @param idField       id字段名，可以与codeField相同
	 * @param codeField     代码字段名
	 * @param nameField     名称字段名
	 * @param orderByField  排序字段名，可以与codeField相同
	 * @param code      代码值
	 * @param useCache  代码表是否进行缓存，缓存可以获取较高的性能，但是不能获取缓存之后更新的数据
	 * @return 
	 * @author: wanghua
	 */
	public String getItemName(String tableName, String codeField,
			String nameField, String orderByField, Object code, boolean useCache){
		return getItemName(tableName, codeField,
				nameField, "", orderByField, code, useCache);
	}
	
	public String getItemNames(String tableName, String codeField,
			String nameField, String orderByField, Object code, boolean useCache){
		return getItemNames(tableName, codeField,
				nameField, "", orderByField, code, useCache);
	}
	
	public String getItemName(String tableName, String codeField,
			String nameField, String parentField, String orderByField, Object code, boolean useCache){
		if(useCache){
			return getCachedItemName(tableName,codeField,nameField,parentField,orderByField,code);
		}else{
			return getRealtimeItemName(tableName,codeField,nameField,code);
		}
	}
	
	public String getItemNames(String tableName, String codeField,
			String nameField, String parentField, String orderByField, Object code, boolean useCache){
		if(useCache){
			return getCachedItemNames(tableName,codeField,nameField,parentField,orderByField,code);
		}else{
			return getRealtimeItemNames(tableName,codeField,nameField,code);
		}
	}
	/**
	 * 根据表名，代码，获取代码对应的名称
	 * 功能描述：
	 * @param tableName 代码表名
	 * @param code 代码
	 * @return 名称
	 * @author: wanghua
	 */
	public String getCachedItemName(String tableName,String codeField,
			String nameField, String orderByField, Object code){
		return getCachedItemName(tableName, codeField, nameField, "", orderByField, code);
	}
	public String getCachedItemName(String tableName, String codeField,
			String nameField, String parentField, String orderByField, Object code){
		if(s_dmDataSource == null) {
			return "";
		}
		if(code == null || code.toString().length()==0) {
			return "";
		}
		tableName = tableName.toUpperCase();
		CodeTable table = tables.get(tableName);
		if(table == null){
			synchronized(dmdict){
				if(table == null){
					try{
					table = s_dmDataSource.fillDMTable(tableName,codeField,nameField,parentField,orderByField);
					tables.put(tableName, table);
					}catch(Exception e){
						System.out.println(e.getMessage());
					}
				}
			}
		}
		if(table != null){
			return table.getName(code);
		}
		return code.toString();
	} 
	
	public String getCachedItemNames(String tableName, String codeField,
			String nameField, String parentField, String orderByField, Object code){
		if(s_dmDataSource == null) {
			return "";
		}
		if(code == null || code.toString().length()==0) {
			return "";
		}
		tableName = tableName.toUpperCase();
		CodeTable table = tables.get(tableName);
		if(table == null){
			synchronized(dmdict){
				if(table == null){
					try{
					table = s_dmDataSource.fillDMTable(tableName,codeField,nameField,parentField,orderByField);
					tables.put(tableName, table);
					}catch(Exception e){
						System.out.println(e.getMessage());
					}
				}
			}
		}
		if(table != null){
			String[] codes = code.toString().split("\\|");
			List<String> names = new ArrayList<>();
			for(String codex : codes){
				names.add(table.getName(codex));
			}
			String namesStr = StringUtils.join(names, '|');
			return namesStr;
		}
		return "";
	} 
	
	/***
	 * 每次都从数据库中获取名称
	 * 功能描述：
	 * @param tableName
	 * @param idField
	 * @param codeField
	 * @param nameField
	 * @param orderByField
	 * @param code
	 * @return 
	 * @author: wanghua
	 */
	public String getRealtimeItemName(String tableName,String codeField,
			String nameField, Object code){
		if(s_dmDataSource == null) {
			return "";
		}
		if(code == null) {
			return "";
		}
		String name = s_dmDataSource.getCodeName(tableName, codeField, nameField, code.toString());
		return name;
	}
	
	public String getRealtimeItemNames(String tableName,String codeField,
			String nameField, Object code){
		if(s_dmDataSource == null) {
			return "";
		}
		if(code == null) {
			return "";
		}
		String name = s_dmDataSource.getCodeNames(tableName, codeField, nameField, code.toString());
		return name;
	}
	/**
	 * 获取指定表的所有字典值的列表
	 * dmClazz必须包含CodeTableInfoAnnotation注解
	 * 功能描述：
	 * @param dmClazz dmClazz必须包含CodeTableInfoAnnotation注解
	 * @return 
	 * @author: wanghua
	 */
	public List<CodeItem> getItems(Class<?> dmClazz, boolean userCache){
		CodeTableInfoAnnotation anno = dmClazz.getAnnotation(CodeTableInfoAnnotation.class);
		if(anno != null){
			List<CodeItem> list = getItems(anno.TableName(), anno.CodeField(),
					anno.NameField(),anno.ParentField(), anno.OrderField(), userCache);
			return list;
		}else {
			return null;
		}
	}
	
	/**
	 * 获取指定表的所有字典值的列表
	 * 功能描述：
	 * @param tableName
	 * @param idField
	 * @param codeField
	 * @param nameField
	 * @param orderByField
	 * @param userCache 是否使用缓存数据
	 * @return 
	 * @author: wanghua
	 */
	public List<CodeItem> getItems(String tableName , String codeField,String nameField, 
			String parentField, String orderByField, boolean userCache){
		if(s_dmDataSource == null) {
			return null; 
		}
		tableName = tableName.toUpperCase();
		CodeTable table = null;
		if(userCache){
			table = tables.get(tableName);
		}
		if(table == null){
			synchronized(dmdict){
				if(table == null){
					try{
					table = s_dmDataSource.fillDMTable(tableName,codeField,nameField,
							parentField, orderByField);
					tables.put(tableName, table);
					}catch(Exception e){
						System.out.println(e.getMessage());
					}
				}
			}
		}
		if(table != null){
			return table.getItemlist();
		}else {
			return null;
		}
	}
	/**获取指定表的所有字典值的列表(使用缓存)*/
	public List<CodeItem> getItems(String tableName , String codeField,String nameField, 
			String parentField, String orderByField){
		return getItems( tableName ,  codeField, nameField, parentField, orderByField, true);
	}
	
	public void clearDMTable(String tableName){
		tableName = tableName.toUpperCase();
		tables.remove(tableName);
	}
	
	public String createHtmlSelectOptions(String dmTableName, String codeField, String nameField, String orderField, String selectedValue, boolean userCache){
		return createHtmlSelectOptions(dmTableName, codeField, nameField, "", orderField, selectedValue, userCache);
	}
	
	public String createHtmlSelectOptions(String dmTableName, String codeField, String nameField, String parentField, String orderField, String selectedValue, boolean userCache){
		StringBuilder sbText = new StringBuilder();
		List<CodeItem> items = getItems(dmTableName, codeField, nameField, parentField, orderField, userCache);
		if (items==null)
		{
			return null;
		} else
		{
			for(CodeItem item : items){
				String selected = "";
				if(selectedValue != null && selectedValue.equals(item.getCode())){
					selected = "selected=\"selected\"";
				}
				sbText.append("<option ").append(selected).append(" value=\"");
				sbText.append(item.getCode()).append("\">").append(item.getName()).append("</option>");
			}
		}
		
		return sbText.toString();
	}
	public String createHtmlSelectOptions(String dmTableName, String codeField, String nameField, String orderField, String selectedValue){
		return createHtmlSelectOptions(dmTableName, codeField, nameField, "", orderField, selectedValue, false);
	}
	
	public String createHtmlSelectOptions(String dmTableName, String codeField, String nameField, String parentField, String orderField, String selectedValue){
		return createHtmlSelectOptions(dmTableName, codeField, nameField, parentField, orderField, selectedValue, false);
	}
}
